package com.hue.spring.servlet;

import com.hue.spring.ApplicationContext;
import com.hue.spring.annotation.RequestParam;
import com.hue.spring.config.Configuration;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 前端控制器
 */
public class DispatchServlet extends HttpServlet {
    //ioc的子容器，存储了所有controller实例
    private Map<String, Object> controllerMap = new ConcurrentHashMap<>();

    //存储了所有url和Method的关系
    private Map<String, Method> urlMethodMap = new ConcurrentHashMap<>();

    //存储url和beanName的关系
    private Map<String, String> urlBeanNameMap = new ConcurrentHashMap<>();

    /**
     * dispatchServlet的初始化方法
     *
     * @param config
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig config) {
        //初始化ioc容器,并为几个映射容器赋值
        new ApplicationContext(Configuration.class, controllerMap, urlMethodMap, urlBeanNameMap);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //得到uri路径
        String uri = req.getRequestURI();
        String mapping = uri.replace(req.getContextPath(), "");
        //根据mapping获取执行的方法和实例
        Method method = urlMethodMap.get(mapping);
        if (method != null) {
            //得到执行这个方法的bean的名字
            Object beanName = urlBeanNameMap.get(mapping);
            //根据名字得到这个bean
            Object bean = controllerMap.get(beanName);
            try {
                //获取该方法参数
                Parameter[] parameters = method.getParameters();
                Object args[] = new Object[parameters.length];
                for (int i = 0; i < parameters.length; i++) {
                    if (parameters[i].getType() == HttpServletRequest.class) {
                        args[i] = req;
                    } else if (parameters[i].getType() == HttpServletResponse.class) {
                        args[i] = resp;
                    } else if (parameters[i].getType() == String.class) {
                        //得到参数的名字
                        String value = parameters[i].getAnnotation(RequestParam.class).value();
                        String parameter = req.getParameter(value);
                        args[i] = parameter;
                    }
                }
                //执行方法
//                method.setAccessible(true);
                method.invoke(bean, args);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}
